package com.example.monitor.util.redis;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.DefaultIdStrategy;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

/**
 * 序列化对象帮助类
 * 
 * @author wangkai
 * @date 2016年12月29日 下午5:43:29
 */
public class ProtostuffUtil {

	private static Map<Class<?>, Schema<?>> cacheShema = new HashMap<Class<?>, Schema<?>>();

	@SuppressWarnings("unchecked")
	private static <T> Schema<T> getSchema(Class<T> clazz) {
		Schema<T> schema = (Schema<T>) cacheShema.get(clazz);
		if (schema == null) {
			synchronized (Schema.class) {
				if (schema == null) {
					schema = RuntimeSchema.getSchema(clazz,
							new DefaultIdStrategy());
					cacheShema.put(clazz, schema);
				}
			}
		}

		return schema;
	}

	/**
	 * 序列化对象<T>
	 * 
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> byte[] ObjeSerialize(T obj) {
		if (obj == null) {
			throw new RuntimeException("序列化对象(" + obj + ")为空!");
		}
		Schema<T> schema = (Schema<T>) getSchema(obj.getClass());
		LinkedBuffer buffer = LinkedBuffer
				.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
		try {
			return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
		} catch (Exception e) {
			System.err.println("序列化对象(" + obj + ")出错!");
			return null;
		} finally {
			buffer.clear();
		}
	}

	/**
	 * 反序列化对象<T>
	 * 
	 * @param objByte
	 * @param clazz
	 * @return
	 */
	public static <T> T deserialize(byte[] objByte, Class<T> clazz) {
		if (objByte == null || objByte.length == 0) {
			System.err.println("反序列化对象发生异常，byte为空");
		}
		T instance = null;
		try {
			instance = clazz.newInstance();
			Schema<T> schema = getSchema(clazz);
			ProtostuffIOUtil.mergeFrom(objByte, instance, schema);
		} catch (Exception e) {
			System.err.println("序列化对象(" + clazz.getName() + ")出错!");
		}
		return instance;
	}

	/**
	 * 序列化list<T>对象
	 * 
	 * @param list
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> byte[] serializeList(List<T> list) {
		if (list == null || list.isEmpty()) {
			System.err.println("序列化对象列表 list发生异常,list对象为空或里面没有数据!");
			return null;
		}
		Schema<T> schema = (Schema<T>) getSchema(list.get(0).getClass());
		LinkedBuffer buffer = LinkedBuffer
				.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
		byte[] protostuff = null;
		ByteArrayOutputStream bos = null;
		try {
			bos = new ByteArrayOutputStream();
			ProtostuffIOUtil.writeListTo(bos, list, schema, buffer);
			protostuff = bos.toByteArray();
		} catch (Exception e) {
			System.err.println("序列化对象列表 list发生异常!" + e.getMessage());
		} finally {
			try {
				if (bos != null) {
					bos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			buffer.clear();
		}
		return protostuff;
	}

	/**
	 * 反序列化list<T>
	 * 
	 * @param listByte
	 * @param clazz
	 * @return
	 */
	public static <T> List<T> deserializeList(byte[] listByte, Class<T> clazz) {
		if (listByte == null || listByte.length == 0) {
			System.err.println("反序列化list对象发生异常，byte为空");
			return null;
		}
		Schema<T> schema = (Schema<T>) getSchema(clazz);
		List<T> result = null;
		ByteArrayInputStream in = null;
		try {
			in = new ByteArrayInputStream(listByte);
			result = ProtostuffIOUtil.parseListFrom(in, schema);
		} catch (Exception e) {
			System.out.println("反序列化对象列表 list发生异常!" + e.getMessage());
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
}
